package com.kymatrix.kycarbon.xsmd.common.util;

import com.kymatrix.kycarbon.xsmd.common.constants.Constant;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;


/**
 * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
 */
public class StringUtil extends org.apache.commons.lang3.StringUtils {
    private static final char SEPARATOR = '_';
    private static final String CHARSET_NAME = StandardCharsets.UTF_8.toString();

    private static Random random;

    static {
        try {
            random = SecureRandom.getInstanceStrong();
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private StringUtil() {
        throw new IllegalStateException(Constant.FAILED);
    }

    /**
     * 匹配数字正则
     */
    private static final Pattern PATTERN_NUM = Pattern.compile("\\d+");

    /**
     * 匹配非数字
     */
    private static final Pattern PATTERN_NOT_NUM = Pattern.compile("\\D+");

    /**
     * 转换为字节数组
     */
    public static byte[] getBytes(String str) {
        if (str != null) {
            try {
                return str.getBytes(CHARSET_NAME);
            } catch (UnsupportedEncodingException e) {
                return new byte[0];
            }
        } else {
            return new byte[0];
        }
    }

    /**
     * 转换为字节数组
     */
    public static String toString(byte[] bytes) {
        try {
            return new String(bytes, CHARSET_NAME);
        } catch (UnsupportedEncodingException e) {
            return EMPTY;
        }
    }

    /**
     * 是否包含字符串
     *
     * @param str  验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inString(String str, String... strs) {
        if (str != null) {
            for (String ss : strs) {
                if (str.equals(trim(ss))) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 替换掉HTML标签方法
     *     public static String replaceHtml(String html) {
     *         if (isBlank(html)) {
     *             return "";
     *         }
     *         String regEx = "<.+?>";
     *         Pattern pattern = Pattern.compile(regEx);
     *         Matcher matcher = pattern.matcher(html);
     *         return matcher.replaceAll("");
     *     }
     */


    /**
     * 去除掉字符串尾部的字符，比如说","
     */
    public static String trimEnd(String str, String tail) {
        if (tail.length() >= str.length()) {
            return str;
        }
        String temp = str.substring(str.length() - tail.length(), str.length());
        if (tail.equals(temp)) {
            return trimEnd(str.substring(0, str.length() - tail.length()), tail);
        } else {
            return str;
        }
    }

    /**
     * 转换为Double类型
     */
    public static Double toDouble(Object val) {
        if (val == null || "".equals(val) || "null".equals(val)) {
            return 0D;
        }
        try {
            return Double.valueOf(trim(val.toString()));
        } catch (Exception e) {
            return 0D;
        }
    }

    /**
     * 转换为Float类型
     */
    public static Float toFloat(Object val) {
        return toDouble(val).floatValue();
    }

    /**
     * 转换为Long类型
     */
    public static Long toLong(Object val) {
        return toDouble(val).longValue();
    }

    /**
     * 转换为String类型
     */
    public static String toString(Object val) {
        if (val == null || "null".equals(val)) {
            return "";
        }
        return val.toString();
    }

    /**
     * 转换为Integer类型
     */
    public static Integer toInteger(Object val) {
        return toLong(val).intValue();
    }

    /**
     * 获得用户远程地址
     */
    public static String getRemoteAddr(HttpServletRequest request) {
        String remoteAddr = request.getHeader("X-Real-IP");
        if (isBlank(remoteAddr)) {
            remoteAddr = request.getHeader("X-Forwarded-For");
        } 
        
        if (isBlank(remoteAddr)) {
            remoteAddr = request.getHeader("Proxy-Client-IP");
        }
        
        if (isNotBlank(remoteAddr)) {
            remoteAddr = request.getHeader("WL-Proxy-Client-IP");
        }
        
        return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
        
    }

    /**
     * 驼峰命名法工具
     *
     * @return toCamelCase(" hello_world ") == "helloWorld"
     *     toCapitalizeCamelCase("hello_world") == "HelloWorld"
     *     toUnderScoreCase("helloWorld") = "hello_world"
     */
    public static String toCamelCase(String paramStr) {
        if (paramStr == null) {
            return null;
        }

        paramStr = paramStr.toLowerCase();

        StringBuilder sb = new StringBuilder(paramStr.length());
        boolean upperCase = false;
        for (int i = 0; i < paramStr.length(); i++) {
            char cc = paramStr.charAt(i);

            if (cc == SEPARATOR) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(cc));
                upperCase = false;
            } else {
                sb.append(cc);
            }
        }

        return sb.toString();
    }

    /**
     * 驼峰命名法工具
     *
     * @return toCamelCase(" hello_world ") == "helloWorld"
     *     toCapitalizeCamelCase("hello_world") == "HelloWorld"
     *     toUnderScoreCase("helloWorld") = "hello_world"
     */
    public static String toCapitalizeCamelCase(String paramStr) {
        if (paramStr == null) {
            return null;
        }
        paramStr = toCamelCase(paramStr);
        return paramStr.substring(0, 1).toUpperCase() + paramStr.substring(1);
    }

    /**
     * 驼峰命名法工具
     *
     * @return toCamelCase(" hello_world ") == "helloWorld"
     *     toCapitalizeCamelCase("hello_world") == "HelloWorld"
     *     toUnderScoreCase("helloWorld") = "hello_world"
     */
    public static String toUnderScoreCase(String paramStr) {
        if (paramStr == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        boolean upperCase = false;
        for (int i = 0; i < paramStr.length(); i++) {
            char cc = paramStr.charAt(i);

            boolean nextUpperCase = true;

            if (i < (paramStr.length() - 1)) {
                nextUpperCase = Character.isUpperCase(paramStr.charAt(i + 1));
            }

            if ((i > 0) && Character.isUpperCase(cc)) {
                if (!upperCase || !nextUpperCase) {
                    sb.append(SEPARATOR);
                }
                upperCase = true;
            } else {
                upperCase = false;
            }

            sb.append(Character.toLowerCase(cc));
        }

        return sb.toString();
    }


    /**
     * 转换为JS获取对象值，生成三目运算返回结果
     * @param objectString 对象串
     */
    public static String jsGetVal(String objectString) {
        StringBuilder result = new StringBuilder();
        StringBuilder val = new StringBuilder();
        String[] vals = split(objectString, ".");
        for (int i = 0; i < vals.length; i++) {
            val.append("." + vals[i]);
            result.append("!" + (val.substring(1)) + "?'':");
        }
        result.append(val.substring(1));
        return result.toString();
    }

    /**
     * 首字母转换成大写
     */
    public static String toUpperCase(String str) {
        return str.replaceFirst(str.substring(0, 1), str.substring(0, 1).toUpperCase());
    }

    /**
     * 首字母转成小写
     */
    public static String toLowerCase(String str) {
        return str.replaceFirst(str.substring(0, 1), str.substring(0, 1).toLowerCase());
    }

    /**
     * 判断子字符串是不是为空
     */
    public static boolean isNull(String str) {
        return null == str || "".equals(str);
    }

    /**
     * 去掉 字符串尾部的
     * @param str str
     * @return 不以/结尾的新字符创
     */
    public static String dropStr(String str) {
        String teml = str.substring(str.length() - 1, str.length());
        if ("/".equals(teml)) {
            //是以/结尾 就
            return dropStr(str.substring(0, str.length() - 1));
        } else {
            return str;
        }

    }

    /**
     * 生成随机数字验证码
     */
    public static String getRandomNum(int length) { 
        //length表示生成字符串的长度
        String base = "6482570319";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    /**
     * double 乘法
     */
    public static double mul(double d1, double d2) {
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.multiply(bd2).doubleValue();
    }


    /**
     * double 相加
     */
    public static double sum(double d1, double d2) {
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.add(bd2).doubleValue();
    }


    /**
     * double 相减
     */
    public static double sub(double d1, double d2) {
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.subtract(bd2).doubleValue();
    }

    /**
     * double 除法
     */
    public static double div(double d1, double d2, int scale) {
        //  当然在此之前，你要判断分母是否为0，
        //  为0你可以根据实际需求做相应的处理

        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.divide(bd2, scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 判断一个字符串是否都为数字
     */
    public static boolean isDigit(String strNum) {
        Matcher matcher = PATTERN_NUM.matcher(strNum);
        return matcher.matches();
    }

    /**
     * 防止sql注入
     */
    public static boolean sqlInj(String str) {
        String injStr = "':and:exec:insert:select:delete:update:count:*:%:chr:" 
                + "mid:master:truncate:char:declare:;:or:-:+:,";
        String[] injStra = injStr.split(":");
        for (int i = 0; i < injStra.length; i++) {
            if (str.indexOf(injStra[i]) != -1) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取真正的字符串值,将字符串null置为真正的null
     */
    public static String getRelString(String str) {
        if (StringUtil.isNotBlank(str) && "null".equals(str)) {
            str = null;
        }
        return str;
    }

    /**
     * 获取真正的字符串值,将字符串null置为真正的null
     */
    public static String getUserNameIdHash(String username, String id) {
        StringBuilder userInfo = new StringBuilder();
        userInfo.append(id).append(username);
        return sha1IdAndName(userInfo.toString());
    }

    /**
     * 对字符串进行散列, 支持md5与sha1算法.
     */
    public static String sha1IdAndName(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-512");


            byte[] result = digest.digest(input.getBytes());

            return Base64.getEncoder().encodeToString(result);
        } catch (GeneralSecurityException e) {
            throw Exceptions.unchecked(e);
        }
    }

    /**
     * 去除指定字符串中的 中英文空格，tab，回车
     */
    public static String genValidInput(String str) {
        if (null != str) {
            String regex = "\\s+";
            str = str.replaceAll(regex, "");
        }
        return str;
    }

    /**
     * subStrByLastStr
     */
    public static String subStrByLastStr(String str, String lastStr) {
        if (isNotBlank(str)) {
            int index = str.lastIndexOf(lastStr);
            if (-1 != index) {
                str = str.substring(0, index);
            }
        }
        return str;
    }

    /**
     * 保留两位小数，四舍五入的一个老土的方法
     */
    public static Double formatDouble(double value) {
        return (double) Math.round(value * 100);
    }

    /**
     * @param typeStr 编码类型
     */
    public static String generateNo(String typeStr) {

        StringBuilder orderNo = new StringBuilder().append(typeStr);
        //获取时间戳
        String timeStr = DateUtil.formatDate(new Date(), "yyyyMMddHHmmss");
        orderNo.append(timeStr);
        //增加4位随机数
        orderNo.append(getRandomNum(4));
        return orderNo.toString();

    }

    /**
     * 获取URL HOST
     */
    public static String getHost(String link) throws MalformedURLException {
        URL url;
        String host = "";
        url = new URL(link);
        host = url.getHost();
        return host;
    }

    /**
     * 根据索引获取字母
     */
    public static String getLetter(int index) {
        return String.valueOf((char) (96 + index)).toUpperCase();
    }

    /**
     * 获取字符串中的所有数字
     */
    public static List<String> getNums(String str) {
        String[] numArr = PATTERN_NOT_NUM.split(str.trim());
        List<String> list = new ArrayList<>();
        if (numArr.length > 0) {
            for (String res : numArr) {
                if (StringUtil.isNotBlank(res)) {
                    list.add(res);
                }
            }
        }
        return list;

    }

    /**
     * 获取字符串最后的数字
     */
    public static String getLastNum(String str) {
        List<String> list = getNums(str);
        if (!list.isEmpty()) {
            return list.get(list.size() - 1);
        }
        return "0";
    }

    /**
     * 如果字符串为空则返回 default否则返回字符串本身
     */
    public static String getDefaultIfEmpty(String str, String defaultVal) {
        if (isEmpty(str)) {
            return defaultVal;
        }
        return str;
    }

    /**
     * 如果字符串为空则返回 空串否则返回字符串本身
     */
    public static String getIfEmpty(String str) {
        return getDefaultIfEmpty(str, "");
    }

}
